<!--
 * @Descripttion: 课堂分析详情-教师行为-活动区域
 * @version: V1.0.0.1
 * @Author: zhaozhenzhuo
 * @Date: 2025-10-27 10:09:06
 * @LastEditors: zhaozhenzhuo
 * @LastEditTime: 2025-10-27 10:09:06
-->
<template>
	<div class="teacher-trajectory-wrapper">
		<div class="module-title-wrapper">
			<p>活动区域</p>
			<img v-if="false" src="@/assets/images/lessonAnalysisDetails/text-edit-normal.png" />
		</div>
		<!-- 描述 -->
		<div class="detail">
			<p
				v-if="
					teacherPathInfo &&
					teacherPathInfo.lessonCode &&
					(teacherPathInfo.lecternAreaDuration ||
						teacherPathInfo.teachAreaDuration ||
						teacherPathInfo.studentAreaDuration)
				"
				v-html="teacherPathDesc"
			></p>

			<p v-if="teacherPathInfo && teacherPathInfo.lessonStartLecternAreaProp >= 0.7">
				在上课初始阶段，老师站在讲桌前，有助于营造一个相对专注的开场氛围，让学生迅速进入上课状态。
			</p>
			<p v-if="teacherPathInfo && teacherPathInfo.lecternAreaPersistDurationList?.length">
				在<span v-for="(item, index) in teacherPathInfo.lecternAreaPersistDurationList" :key="index"
					>{{ formatTime(item.startTime, 'HH:mm:ss') }}至{{
						formatTime(item.endTime, 'HH:mm:ss')
					}}，</span
				>老师长时间停留在讲桌区，可能导致学生注意力下降。
			</p>
			<p
				v-if="
					teacherPathInfo &&
					teacherPathInfo.lecternAreaDuration / teacherPathTimeDuration >= 0.5 &&
					behaviorData &&
					(behaviorData.leaningTimes || 0) +
						(behaviorData.walkingTimes || 0) +
						(behaviorData.writingTimes || 0) >=
						50
				"
			>
				老师较长时间在讲台区进行系统性讲解知识，并且有较多的讲解指示和写板书的动作，有助于提高学生注意力，是一个不错的讲授型课堂。
			</p>
			<p
				v-if="
					teacherPathInfo &&
					teacherPathInfo.lecternAreaDuration / teacherPathTimeDuration >= 0.5 &&
					behaviorData &&
					(behaviorData.leaningTimes || 0) +
						(behaviorData.walkingTimes || 0) +
						(behaviorData.writingTimes || 0) <
						50
				"
			>
				老师较长时间在讲台区进行系统性讲解知识，建议多结合肢体动作、板书等来提高学生注意力，也可以走近学生，与学生展开互动。
			</p>
			<p v-if="teacherPathInfo && teacherPathInfo.toStudentAreaTimes >= 3">
				老师在讲课过程中{{
					teacherPathInfo.toStudentAreaTimes
				}}次走入学生中间，拉近师生距离，有助于提高课堂专注度和活跃度。
			</p>
			<p v-if="teacherPathInfo && teacherPathInfo.patrolTimes">
				老师{{
					teacherPathInfo.patrolTimes
				}}次走入学生区巡视，有利于掌握学生学习情况，提高学生注意力。
			</p>
		</div>
		<div class="trajectory-chart-wrap">
			<div
				v-if="teacherPathInfo && teacherPathInfo.lessonCode"
				class="activity-behavior-echarts-wrap"
			></div>

			<!-- 课堂轨迹图 -->
			<div class="classroom-wrap">
				<img
					class="classroom-backage-img"
					src="@/assets/images/lessonAnalysisDetails/classroom-background.png"
					alt=""
				/>

				<!-- 热力图 -->
				<img
					v-if="teacherPathInfo?.lecternAreaDuration"
					class="lectern-area-item"
					:src="lecternAreaImgList[areaList.indexOf(teacherPathInfo.lecternAreaDuration)]"
					alt=""
				/>

				<img
					v-if="teacherPathInfo?.teachAreaDuration"
					class="teach-area-item"
					:src="teachAreaImgList[areaList.indexOf(teacherPathInfo.teachAreaDuration)]"
					alt=""
				/>

				<img
					v-if="teacherPathInfo?.studentAreaDuration"
					class="student-area-item"
					:src="studentAreaImgList[areaList.indexOf(teacherPathInfo.studentAreaDuration)]"
					alt=""
				/>

				<!-- 讲桌 -->
				<div class="card-item card-item-desk">
					<div class="desc-wrap">
						<div class="title orange">讲桌前</div>
						<div class="card-desc">
							本堂课教师在讲桌区域停留{{
								teacherPathInfo?.lecternAreaDuration || teacherPathInfo?.lecternAreaDuration === 0
									? formatSecToStr(teacherPathInfo.lecternAreaDuration)
									: '-秒'
							}}，占比:
							<span class="orange ali-blod-family">
								{{
									teacherPathTimeDuration &&
									(teacherPathInfo?.lecternAreaDuration ||
										teacherPathInfo?.lecternAreaDuration === 0)
										? teacherPathInfo.lecternAreaRate
										: '-'
								}}%
							</span>
						</div>
					</div>
				</div>

				<!-- 讲台 -->
				<div class="card-item card-item-podium">
					<div class="desc-wrap">
						<div class="title green">讲台区</div>
						<div class="card-desc">
							本堂课教师在讲台区域停留{{
								teacherPathInfo?.teachAreaDuration || teacherPathInfo?.teachAreaDuration === 0
									? formatSecToStr(teacherPathInfo.teachAreaDuration)
									: '-秒'
							}}，占比:
							<span class="green ali-blod-family">
								{{
									teacherPathTimeDuration &&
									(teacherPathInfo?.teachAreaDuration || teacherPathInfo?.teachAreaDuration === 0)
										? teacherPathInfo.teachAreaRate
										: '-'
								}}%
							</span>
						</div>
					</div>
				</div>

				<!-- 学生区 -->
				<div class="card-item card-item-student">
					<div class="desc-wrap">
						<div class="title blue">学生区</div>
						<div class="card-desc">
							本堂课教师在学生区域停留{{
								teacherPathInfo?.studentAreaDuration || teacherPathInfo?.studentAreaDuration === 0
									? formatSecToStr(teacherPathInfo.studentAreaDuration)
									: '-秒'
							}}，占比:
							<span class="blue ali-blod-family">
								{{
									teacherPathTimeDuration &&
									(teacherPathInfo?.studentAreaDuration ||
										teacherPathInfo?.studentAreaDuration === 0)
										? teacherPathInfo.studentAreaRate
										: '-'
								}}%
							</span>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import type {
	CustomSeriesRenderItemParams,
	CustomSeriesRenderItemAPI,
	ECElementEvent
} from 'echarts';
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';
import { formatTime, formatSecToStr, roundArrayWithSum } from '@/assets/js/utils';
import type {
	CourseListItemType,
	AnalysisResultType,
	TeacherPathInfoType,
	PathInfoItemType,
	BehaviorDataType,
	PreviewInfoType,
	RealBreakTimeItemType
} from './TeacherTrajectory.type';
import { getErrorMessage, getLessonTeacherPathAPI } from '@/api/index';
import lecternAreaSmallImg from '@/assets/images/lessonAnalysisDetails/lectern-area-small.png';
import lecternAreaMiddleImg from '@/assets/images/lessonAnalysisDetails/lectern-area-middle.png';
import lecternAreaBigImg from '@/assets/images/lessonAnalysisDetails/lectern-area-big.png';
import teachAreaSmallImg from '@/assets/images/lessonAnalysisDetails/teach-area-small.png';
import teachAreaMiddleImg from '@/assets/images/lessonAnalysisDetails/teach-area-middle.png';
import teachAreaBigImg from '@/assets/images/lessonAnalysisDetails/teach-area-big.png';
import studentAreaSmallImg from '@/assets/images/lessonAnalysisDetails/student-area-small.png';
import studentAreaMiddleImg from '@/assets/images/lessonAnalysisDetails/student-area-middle.png';
import studentAreaBigImg from '@/assets/images/lessonAnalysisDetails/student-area-big.png';

const props = withDefaults(
	defineProps<{
		queryObj: {
			lessonInfo: CourseListItemType | null;
			aiScoreResult: AnalysisResultType | null;
			offsetTime: number;
			videoBeginTime: number;
		} | null;
		behaviorData: BehaviorDataType | null;
		realBreakTimeArr: RealBreakTimeItemType[] | null;
	}>(),
	{
		queryObj: null,
		behaviorData: null,
		realBreakTimeArr: null
	}
);

const lessonInfo = computed(() => props.queryObj?.lessonInfo);
const aiScoreResult = computed(() => props.queryObj?.aiScoreResult);
const videoBeginTime = computed(() => props.queryObj?.videoBeginTime);

// 讲桌图片列表
const lecternAreaImgList = ref<string[]>([
	lecternAreaSmallImg,
	lecternAreaMiddleImg,
	lecternAreaBigImg
]);
// 讲台区图片列表
const teachAreaImgList = ref<string[]>([teachAreaSmallImg, teachAreaMiddleImg, teachAreaBigImg]);
// 学生区图片列表
const studentAreaImgList = ref<string[]>([
	studentAreaSmallImg,
	studentAreaMiddleImg,
	studentAreaBigImg
]);

watch(
	() => props.queryObj,
	(val) => {
		if (val && val.aiScoreResult && val.lessonInfo) {
			nextTick(() => {
				getLessonTeacherPath();
			});
		}
	},
	{ immediate: true }
);

// 窗口大小与1920的比值
const rate = ref(
	(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 1920
);

onMounted(() => {
	window.addEventListener('resize', resizeHandler);
});

onUnmounted(() => {
	window.removeEventListener('resize', resizeHandler);

	// 清理 DOM 事件监听器
	if (chartDom.value) {
		if (mousedownHandler.value) {
			chartDom.value.removeEventListener('mousedown', mousedownHandler.value);
			mousedownHandler.value = null;
		}
		if (clickHandler.value) {
			chartDom.value.removeEventListener('click', clickHandler.value);
			clickHandler.value = null;
		}
		chartDom.value = null;
	}

	// 清理 ECharts 实例
	if (trajectoryChart.value) {
		trajectoryChart.value.dispose();
		trajectoryChart.value = null;
	}
});

const resizeHandler = () => {
	setTimeout(() => {
		rate.value =
			(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) /
			1920;
		initActivityTrajectoryCharts();
	}, 300);
};

// 轨迹信息
const teacherPathInfo = ref<TeacherPathInfoType | null>(null);
// 图像开始时间
const startTime = ref<number>(0);
// 图像结束时间
const endTime = ref<number>(0);
// 总时长
const teacherPathTimeDuration = ref<number>(0);
// 描述
const teacherPathDesc = ref<string>('');
// 教师所处区域信息列表（由小到大）
const areaList = ref<number[]>([]);
// 老师活动轨迹描述
const getLessonTeacherPath = async () => {
	try {
		const data = await getLessonTeacherPathAPI({
			lessonCode: lessonInfo.value?.code as string
		});

		teacherPathInfo.value = data;
		// 计算老师总停留时间
		if (teacherPathInfo.value) {
			teacherPathInfo.value.totalAreaDuration =
				(data.lecternAreaDuration || 0) +
				(data.teachAreaDuration || 0) +
				(data.studentAreaDuration || 0);
		}

		startTime.value = aiScoreResult.value?.calBeginTime || 0;
		endTime.value = aiScoreResult.value?.calEndTime || 0;

		// 修改pathInfo数据
		const _pathInfo: PathInfoItemType[] = [];
		if (teacherPathInfo.value?.pathInfo && teacherPathInfo.value?.pathInfo.length) {
			teacherPathInfo.value?.pathInfo.forEach((item) => {
				if (item.startTime * 1000 <= startTime.value && item.endTime * 1000 >= endTime.value) {
					_pathInfo.push({
						areaType: item.areaType,
						imageUrl: item.imageUrl,
						x: item.x,
						y: item.y,
						startTime: startTime.value / 1000,
						endTime: endTime.value / 1000
					});
				} else if (
					item.startTime * 1000 <= startTime.value &&
					item.endTime * 1000 < endTime.value &&
					item.endTime * 1000 > startTime.value
				) {
					_pathInfo.push({
						areaType: item.areaType,
						imageUrl: item.imageUrl,
						x: item.x,
						y: item.y,
						startTime: startTime.value / 1000,
						endTime: item.endTime
					});
				} else if (
					item.startTime * 1000 > startTime.value &&
					item.startTime * 1000 < endTime.value &&
					item.endTime * 1000 < endTime.value
				) {
					_pathInfo.push(item);
				} else if (
					item.startTime * 1000 > startTime.value &&
					item.startTime * 1000 < endTime.value &&
					item.endTime * 1000 >= endTime.value
				) {
					_pathInfo.push({
						areaType: item.areaType,
						imageUrl: item.imageUrl,
						x: item.x,
						y: item.y,
						startTime: item.startTime,
						endTime: endTime.value / 1000
					});
				}
			});
		}
		teacherPathInfo.value.pathInfo = _pathInfo;
		// 修改各活动区域时间
		let _lecternAreaDuration = 0;
		let _teachAreaDuration = 0;
		let _studentAreaDuration = 0;
		teacherPathInfo.value.pathInfo.forEach((item) => {
			const _duration = item.endTime - item.startTime;
			if (item.areaType === 'LecternAera') {
				_lecternAreaDuration += _duration;
			} else if (item.areaType === 'TeachAera') {
				_teachAreaDuration += _duration;
			} else if (item.areaType === 'StudentAera') {
				_studentAreaDuration += _duration;
			}
		});

		teacherPathInfo.value.lecternAreaDuration = _lecternAreaDuration;
		teacherPathInfo.value.teachAreaDuration = _teachAreaDuration;
		teacherPathInfo.value.studentAreaDuration = _studentAreaDuration;

		teacherPathTimeDuration.value =
			_lecternAreaDuration + _teachAreaDuration + _studentAreaDuration;

		// 保证各区域时间之和为100%
		const _durationList = roundArrayWithSum(
			[
				(_lecternAreaDuration / teacherPathTimeDuration.value) * 100,
				(_teachAreaDuration / teacherPathTimeDuration.value) * 100,
				(_studentAreaDuration / teacherPathTimeDuration.value) * 100
			],
			0,
			100
		);
		teacherPathInfo.value.lecternAreaRate = _durationList[0] || 0;
		teacherPathInfo.value.teachAreaRate = _durationList[1] || 0;
		teacherPathInfo.value.studentAreaRate = _durationList[2] || 0;

		// 描述
		if (!_teachAreaDuration && !_studentAreaDuration) {
			teacherPathDesc.value =
				'本堂课老师只在<span class="active">讲桌区</span>活动，从未走入讲台区和学生区。';
		} else if (!_lecternAreaDuration && !_studentAreaDuration) {
			teacherPathDesc.value =
				'本堂课老师只在<span class="active">讲台区</span>活动，从未走入讲台区和学生区。';
		} else if (!_lecternAreaDuration && !_teachAreaDuration) {
			teacherPathDesc.value =
				'本堂课老师只在<span class="active">学生区</span>活动，从未走入讲台区和讲桌区。';
		} else {
			const _pathList = [
				{
					name: '讲桌前',
					num: _lecternAreaDuration
				},
				{
					name: '讲台区',
					num: _teachAreaDuration
				},
				{
					name: '学生区',
					num: _studentAreaDuration
				}
			].sort((a, b) => b.num - a.num);
			teacherPathDesc.value = `本堂课老师的活动区域主要在<span class="active">${_pathList[0].name}</span>（停留时长最多的区域），偶尔在${_pathList[1].name}（停留时长第二的区域），很少走入${_pathList[2].name}（停留时长最少的区域）。`;
			if (teacherPathInfo.value?.studentAreaDuration / teacherPathTimeDuration.value < 0.1) {
				teacherPathDesc.value += '建议老师多走入学生区，关注学生学习情况，适当与学生互动。';
			} else if (
				teacherPathInfo.value?.lecternAreaDuration / teacherPathTimeDuration.value >=
				0.5
			) {
				teacherPathDesc.value += '建议老师多走入讲台区授课，结合板书和讲解动作更好的开展知识讲授。';
			}
		}

		// 活动区域
		areaList.value = [_lecternAreaDuration, _teachAreaDuration, _studentAreaDuration].sort(
			(a, b) => a - b
		);
		nextTick(() => {
			// 绘制图形
			initActivityTrajectoryCharts();
		});
	} catch (err) {
		console.log(33, err);
		console.error(getErrorMessage(err));
	}
};

// 当前鼠标所在的小块序号
const currentIndex = ref<number>(-1);
// 当前鼠标所在位置的时间
const currentTime = ref<number | null>(null);
// echarts配置项
const echartsOption = ref<Record<string, unknown>>({});
// echarts对象
const trajectoryChart = ref<echarts.ECharts | null>(null);
// 绘制图形
const initActivityTrajectoryCharts = () => {
	if (!teacherPathInfo.value || !teacherPathInfo.value.lessonCode) {
		return false;
	}
	// 颜色数组
	const _statusItemStyleColorMap = {
		LecternAera: '#F9B884',
		TeachAera: '#8AE4A3',
		StudentAera: '#75B2FF'
	};
	// 文字描述数组
	const _statusItemNameMap = {
		LecternAera: '讲桌前',
		TeachAera: '讲台区',
		StudentAera: '学生区'
	};

	const _behaviorsList: Record<string, unknown>[] = teacherPathInfo.value.pathInfo.map((item) => {
		return {
			value: [
				'活动轨迹', // y刻度下标
				formatTime(item.startTime * 1000, 'YYYY-MM-DD HH:mm:ss'), // 开始
				formatTime(item.endTime * 1000, 'YYYY-MM-DD HH:mm:ss'), // 结束
				_statusItemNameMap[item.areaType as keyof typeof _statusItemNameMap]
			],
			itemStyle: {
				color: _statusItemStyleColorMap[item.areaType as keyof typeof _statusItemStyleColorMap]
			}
		};
	});

	// 增加实际休息时间
	if (props.realBreakTimeArr?.length) {
		props.realBreakTimeArr.forEach((item) => {
			_behaviorsList.push({
				value: [
					'活动轨迹', // y刻度下标
					formatTime(item.startTime, 'YYYY-MM-DD HH:mm:ss'), // 开始
					formatTime(item.endTime, 'YYYY-MM-DD HH:mm:ss') // 结束
				],
				itemStyle: {
					color: 'rgba(34, 172, 56, 0.3)'
				},
				// 标记为实际休息时间，用于识别
				isRealBreakTime: true
			});
		});
	}

	const yData = ['活动轨迹'];
	// 补零
	const addZero = (n: number) => {
		if (n < 10) return `0${n}`;
		return n;
	};
	// 设置矩形
	const renderItem = (params: CustomSeriesRenderItemParams, api: CustomSeriesRenderItemAPI) => {
		const categoryIndex = api.value(0) as number;
		const start = api.coord([api.value(1), categoryIndex]) as number[];
		const end = api.coord([api.value(2), categoryIndex]) as number[];
		const sizeResult = api.size?.([0, 1]) as number[] | undefined;
		const height = (sizeResult?.[1] ?? 0) * 0.2;
		const coordSys = params.coordSys as unknown as {
			x: number;
			y: number;
			width: number;
			height: number;
		};
		// 获取当前数据项
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[3];
		const data = series?.data as Array<Record<string, unknown>>;
		const currentData = data?.[params.dataIndex];
		const isRealBreakTime = currentData?.isRealBreakTime || false;

		// 如果是当前鼠标所在的块，则设置宽度为14px，从小块中心向两边放大
		// 但如果是实际休息时间，则不放大
		const rectShape = echarts.graphic.clipRectByRect(
			{
				x:
					currentIndex.value === params.dataIndex && !isRealBreakTime
						? start[0] + (end[0] - start[0]) / 2 - 7
						: start[0],
				y: start[1] - height / 2 - 3, // 向上偏移3像素 确保居中
				// 将鼠标所在的小块宽度设置为14px，小块最小1px，小于1px的设置为1px
				/* eslint-disable no-nested-ternary */
				width:
					currentIndex.value === params.dataIndex && !isRealBreakTime
						? 14
						: end[0] - start[0] > 0 && end[0] - start[0] < 1
						? 1
						: end[0] - start[0],
				height: 28 * rate.value
			},
			{
				x: coordSys.x,
				y: coordSys.y,
				width: coordSys.width,
				height: coordSys.height
			}
		);
		// 保存一下每个小块的宽度
		if (currentData) {
			currentData.rectWidth = end[0] - start[0];
		}
		return (
			rectShape && {
				type: 'rect',
				transition: ['shape'],
				shape: rectShape,
				style: {
					fill: api.visual('color')
				},
				// 为实际休息时间设置更高的 z 值
				z: isRealBreakTime ? 100 : 1,
				// 确保不响应鼠标事件
				silent: isRealBreakTime
			}
		);
	};

	// 清理旧的事件监听器
	if (chartDom.value) {
		if (mousedownHandler.value) {
			chartDom.value.removeEventListener('mousedown', mousedownHandler.value);
			mousedownHandler.value = null;
		}
		if (clickHandler.value) {
			chartDom.value.removeEventListener('click', clickHandler.value);
			clickHandler.value = null;
		}
	}

	// 绘制图像
	if (trajectoryChart.value) {
		trajectoryChart.value.dispose();
	}
	trajectoryChart.value = echarts.init(
		document.querySelector('.activity-behavior-echarts-wrap') as HTMLElement
	);
	echartsOption.value = {
		legend: {
			show: true,
			selectedMode: false,
			top: '15%',
			// 设置大小
			itemWidth: 12 * rate.value,
			itemHeight: 7 * rate.value,
			// 设置距离
			itemGap: 60 * rate.value,
			// 设置字体大小
			textStyle: {
				fontSize: 14 * rate.value,
				fontFamily: 'Alibaba PuHuiTi',
				color: '#2f2f2f'
			}
		},
		grid: {
			top: '36%',
			bottom: '0%',
			left: '3%',
			right: '3%',
			containLabel: true
		},
		xAxis: {
			type: 'time',
			min: startTime.value,
			max: endTime.value,
			axisLine: {
				show: true,
				lineStyle: {
					color: '#C0C0C0'
				}
			},
			axisLabel: {
				color: '#666666',
				fontSize: 14 * rate.value,
				fontWeight: 400,
				fontFamily: 'Alibaba PuHuiTi',
				formatter: (val: number | string) => {
					const d = new Date(val);
					return `${addZero(d.getHours())}:${addZero(d.getMinutes())}`;
				}
			},
			axisTick: {
				show: true,
				inside: true,
				length: 4,
				lineStyle: {
					color: '#B7B7B7'
				}
			},
			// 显示网格线
			splitLine: {
				show: false,
				lineStyle: {
					color: '#BDC7D4',
					type: 'dashed'
				}
			},
			axisPointer: {
				show: true,
				triggerTooltip: false,
				cursor: 'pointer',
				lineStyle: {
					color: '#0092FF'
				},
				label: {
					show: true,
					margin: -60 * rate.value,
					fontSize: 14 * rate.value,
					fontWeight: 400,
					fontFamily: 'Alibaba PuHuiTi',
					backgroundColor: '#807d8b',
					formatter: (params: { value: number }) => {
						// 保存一下当前的时间
						currentTime.value = params.value;
						return `${formatTime(params.value, 'HH:mm:ss')}`;
					}
				}
			}
		},
		yAxis: {
			type: 'category',
			data: yData,
			axisLine: {
				show: false,
				lineStyle: {
					color: '#BDC7D4'
				}
			},
			axisLabel: {
				show: false,
				fontSize: 16 * rate.value,
				fontWeight: 400,
				fontFamily: 'Alibaba PuHuiTi',
				color: (value?: string | number, index?: number) => {
					const colorList = [
						'#89C7FC',
						'#66B3F4',
						'#2D95ED',
						'#8AE4A3',
						'#6BD689',
						'#F8A751',
						'#F99135',
						'#F97811'
					];
					return colorList[index ?? 0];
				}
			},
			axisTick: {
				show: false
			}
		},
		series: [
			{
				type: 'bar',
				name: '讲桌前',
				itemStyle: {
					color: '#F9B884'
				}
			},
			{
				type: 'bar',
				name: '讲台区',
				itemStyle: {
					color: '#8AE4A3'
				}
			},
			{
				type: 'bar',
				name: '学生区',
				itemStyle: {
					color: '#75B2FF'
				}
			},
			{
				type: 'custom',
				// 数据堆叠（成块显示）
				stack: 'Total',
				renderItem,
				encode: {
					x: [],
					y: [0]
				},
				data: _behaviorsList
			}
		]
	};
	trajectoryChart.value.setOption(echartsOption.value);
	bindClickEvent();
};

// 当前是否点击的是小块，true：点击小块 false：点击空白处
const isClickRect = ref<boolean>(false);
// 节流标识
const flag = ref<boolean>(false);
// 图片信息
const picInfo = ref<PreviewInfoType | null>(null);
// 保存 chartDom 引用和事件处理函数引用，用于清理
const chartDom = ref<HTMLDivElement | null>(null);
const mousedownHandler = ref<((e: MouseEvent) => void) | null>(null);
const clickHandler = ref<((e: MouseEvent) => void) | null>(null);

const emit = defineEmits<{
	(e: 'changeVideoTime', time: number): void; // 切换视频时间
	(e: 'previewShow', info: PreviewInfoType): void;
}>();

// 绑定点击事件
const bindClickEvent = () => {
	/* 点击事件 */
	chartDom.value = document.querySelector('.activity-behavior-echarts-wrap');
	if (chartDom.value) {
		// chart绑定鼠标按下事件
		let _offsetX = 0;
		let _offsetY = 0;

		// 创建并保存 mousedown 事件处理函数
		mousedownHandler.value = (e: MouseEvent) => {
			// 记录一下按下时的坐标
			_offsetX = e.offsetX;
			_offsetY = e.offsetY;
		};

		// 创建并保存 click 事件处理函数
		clickHandler.value = (e: MouseEvent) => {
			// 如果起始点和结束点不在一个位置，就是拖动，不触发点击事件，具体判断条件x、y坐标偏移不超过5px 或 点击的是小块不触发下面的事件
			if (
				e.offsetX - _offsetX > 5 ||
				e.offsetX - _offsetX < -5 ||
				e.offsetY - _offsetY > 5 ||
				e.offsetY - _offsetY < -5 ||
				isClickRect.value
			) {
				return;
			}
			// 获取像素数组
			const _pixelArr: number[] = [e.offsetX, e.offsetY];
			// 如果点击了图像以外的部分，就不触发下面的事件
			if (!trajectoryChart.value?.containPixel('grid', _pixelArr)) {
				return;
			}
			// 设置视频时间
			const _currentTime =
				(currentTime.value || 0) - (videoBeginTime.value || 0) > 0
					? ((currentTime.value || 0) - (videoBeginTime.value || 0)) / 1000
					: 0;
			// 通知视频组件弹框
			emit('changeVideoTime', _currentTime);
		};

		// 绑定事件
		chartDom.value.addEventListener('mousedown', mousedownHandler.value);
		chartDom.value.addEventListener('click', clickHandler.value);
	}

	// 绑定echarts事件
	trajectoryChart.value?.on('mouseover', (params: { dataIndex: number }) => {
		// 只有宽度小于14px的块才走事件
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[3];
		const data = series?.data as Array<Record<string, unknown>>;
		const currentData = data?.[params.dataIndex];

		// 如果是实际休息时间，不处理鼠标事件
		if (currentData?.isRealBreakTime) {
			return;
		}

		if (currentData?.rectWidth && (currentData.rectWidth as number) <= 14 && !flag.value) {
			flag.value = true;
			setTimeout(() => {
				flag.value = false;
			}, 200);
			currentIndex.value = params.dataIndex;
			trajectoryChart.value?.setOption(echartsOption.value);
		}
	});
	trajectoryChart.value?.on('mouseout', () => {
		// 鼠标移出恢复
		if (currentIndex.value !== -1) {
			currentIndex.value = -1;
			trajectoryChart.value?.setOption(echartsOption.value);
		}
	});
	trajectoryChart.value?.on('mousemove', (params: { dataIndex: number }) => {
		// 只有宽度小于14px的块才走事件，防止鼠标移入时不满足条件导致的块大小没有变化的问题
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[3];
		const data = series?.data as Array<Record<string, unknown>>;
		const currentData = data?.[params.dataIndex];

		// 如果是实际休息时间，不处理鼠标事件
		if (currentData?.isRealBreakTime) {
			return;
		}

		if (
			currentData?.rectWidth &&
			(currentData.rectWidth as number) <= 14 &&
			currentIndex.value !== params.dataIndex &&
			!flag.value
		) {
			flag.value = true;
			setTimeout(() => {
				flag.value = false;
			}, 200);
			currentIndex.value = params.dataIndex;
			trajectoryChart.value?.setOption(echartsOption.value);
		}
	});
	trajectoryChart.value?.on('mousedown', () => {
		// 当前点击的是小块
		isClickRect.value = true;
	});
	trajectoryChart.value?.on('click', (params: ECElementEvent) => {
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[3];
		const data = series?.data as Array<Record<string, unknown>>;
		const currentData = data?.[params.dataIndex];

		// 如果是实际休息时间，不处理鼠标事件
		if (currentData?.isRealBreakTime) {
			return;
		}

		const _startTime =
			(teacherPathInfo.value?.pathInfo?.[params.dataIndex]?.startTime as number) * 1000 || 0;
		// 设置视频时间
		const _currentTime =
			_startTime - (videoBeginTime.value || 0) > 0
				? (_startTime - (videoBeginTime.value || 0)) / 1000
				: 0;

		const value = params.value as (string | number)[];
		picInfo.value = {
			transFileUrl: teacherPathInfo.value?.pathInfo[params.dataIndex].imageUrl
				? changeImageURl(teacherPathInfo.value.pathInfo[params.dataIndex].imageUrl)
				: '',
			name: `授课轨迹分析（${value[3] || '未知区域'}）`,
			type: 1,
			videoTime: _currentTime - 1, // 这段行为开始时间对应的视频时间
			analysisType: 1 // 1:老师 2:学生
		};
		emit('previewShow', picInfo.value);
		// 点击事件完成恢复初始值
		setTimeout(() => {
			isClickRect.value = false;
		}, 50);
	});
};

// 拦截更改图片地址
const changeImageURl = (url: string) => {
	if (url.includes('stream?')) {
		return url;
	}
	return `${window.location.protocol}//${window.location.host}/stream?srcUrl=${url}`;
};
</script>

<style lang="scss" scoped>
.teacher-trajectory-wrapper {
	margin-top: 1.6rem;

	.activity-trajectory-desc {
		height: 4rem;
	}

	.lectern-area-item {
		position: absolute;
		left: calc(40rem / 1.5);
		top: 3.5rem;
		width: calc(14.6rem / 1.45);
		height: calc(6.9rem / 1.2);
	}

	.teach-area-item {
		position: absolute;
		right: calc(40rem / 1.5);
		top: 3.5rem;
		width: calc(16.3rem / 1.45);
		height: calc(6.9rem / 1.2);
	}

	.student-area-item {
		position: absolute;
		left: calc(58rem / 1.45);
		top: calc(14.5rem / 1.1);
		width: calc(15.5rem / 1.45);
		height: calc(11.2rem / 1.2);
	}

	.classroom-wrap {
		height: 30rem;
		background-position: center;
		background-repeat: no-repeat;
		position: relative;

		.classroom-backage-img {
			aspect-ratio: 757 / 302;
			height: 20rem;
			position: absolute;
			left: 50%;
			top: 50%;
			transform: translate(-50%, -50%);
		}

		.card-item {
			width: calc(28.5rem / 1.4);
			height: calc(12.6rem / 1.4);
			background-repeat: no-repeat;
			position: absolute;
			background-size: 100% 100%;

			.desc-wrap {
				position: absolute;
				left: 50%;
				top: 50%;
				transform: translate(-50%, -50%);
				margin-top: calc(-1.1rem / 1.4);

				.title {
					font-size: $font-size-small-1;
					text-align: center;
				}

				.card-desc {
					width: calc(23.9rem / 1.4);
					height: calc(4.7rem / 1.4);
					font-size: $font-size-small-1;
					color: $text-color-regular;
					margin-top: calc(2rem / 1.4);
				}
			}

			.orange {
				color: $text-color-warning;
			}

			.green {
				color: $text-color-success;
			}

			.blue {
				color: $text-color-blue;
			}
		}

		.card-item-desk {
			background-image: url('@/assets/images/lessonAnalysisDetails/card.png');
			left: calc(1rem / 1.4);
			top: 50%;
			transform: translateY(-50%);
		}

		.card-item-podium {
			background-image: url('@/assets/images/lessonAnalysisDetails/card.png');
			top: calc(3.6rem / 1.17);
			right: calc(1.3rem / 1.4);
		}

		.card-item-student {
			background-image: url('@/assets/images/lessonAnalysisDetails/card.png');
			top: calc(17.4rem / 1.17);
			right: calc(4rem / 1.4);
		}
	}

	.activity-behavior-echarts-wrap {
		height: 10rem;
	}

	.trajectory-chart-wrap {
		background-color: rgba($color: $bg-block-color-primary, $alpha: 0.9);
	}
}
</style>
